home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- * Portions Copyright (C) 1994 Rafael W. Luebbert
- * Portions Copyright (C) 1995 Jeff Shepherd
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #define _KERNEL
- #include "ixemul.h"
- #include "kprintf.h"
-
- #include <hardware/intbits.h>
- #include <exec/memory.h>
- #include <string.h>
-
- extern void launch_glue (), switch_glue ();
- extern void trap_20 ();
- extern void trap_00 ();
- extern int ix_timer();
-
- static BOOL
- __ix_open_muFS (struct user *ix_u)
- {
- if (muBase)
- {
- /* set up multiuser data's */
- ix_u->u_UserInfo = muAllocUserInfo ();
- if (NULL == ix_u->u_UserInfo)
- return FALSE;
- ix_u->u_fileUserInfo = muAllocUserInfo ();
- if (NULL == ix_u->u_fileUserInfo)
- return FALSE;
-
- ix_u->u_GroupInfo = muAllocGroupInfo ();
- if (NULL == ix_u->u_GroupInfo)
- return FALSE;
- ix_u->u_fileGroupInfo = muAllocGroupInfo ();
- if (NULL == ix_u->u_fileGroupInfo)
- return FALSE;
- }
- return TRUE;
- }
-
- struct ixemul_base *
- ix_open (struct ixemul_base *ixbase)
- {
- /* here we must initialize our `user' structure */
- struct user *ix_u;
- /* an errno for those that later don't set it in ix_startup() */
- static int default_errno;
- /* an h_errno for those that later don't set it in ix_startup() */
- static int default_h_errno;
- struct Task *me;
- char *tmp;
- int a4_size = A4_POINTERS * 4;
-
- me = SysBase->ThisTask;
-
- tmp = (char *)kmalloc(sizeof(struct user) + a4_size);
- if (tmp)
- {
- /* bzero is safe, ie. doesn't need to reference struct user */
- bzero (tmp, sizeof (struct user) + a4_size);
- ix_u = (struct user *)(tmp + a4_size);
-
- /* remember old state */
- ix_u->u_otask_flags = me->tc_Flags;
- ix_u->u_olaunch = me->tc_Launch;
- ix_u->u_oswitch = me->tc_Switch;
- ix_u->u_otrap_code = me->tc_TrapCode;
- ix_u->u_otrap_data = me->tc_TrapData;
-
- NewList ((struct List *) &ix_u->u_md.md_list);
-
- ix_u->u_mdp = &ix_u->u_md;
-
- KPRINTF (("ix_open: ix_u = $%lx, ix_open @$lx\n", ix_u, ix_open));
-
- me->tc_TrapData = (APTR)ix_u;
-
- if (betterthan68000())
- me->tc_TrapCode = trap_20;
- else
- me->tc_TrapCode = trap_00;
-
- initstack();
-
- /* setup the p_sigignore mask correctly */
- siginit (ix_u);
- me->tc_SigRecvd &= 0x0fff;
-
- /* this library is a replacement for any c-library, thus we should be
- * started at the START of a program, and out of 16 available signals
- * these calls simply have to succeed... I know I'm a lazy guy ;-) */
- ix_u->u_sleep_sig = AllocSignal (-1);
- ix_u->u_pipe_sig = AllocSignal (-1);
-
- ix_u->u_ixbase = ixbase;
- ix_u->u_errno = &default_errno;
- ix_u->u_h_errno = &default_h_errno;
-
- /* ixnet.library is loaded iff ixbase->ix_network_type != IX_NETWORK_NONE */
- if (ixbase->ix_network_type != IX_NETWORK_NONE)
- ix_u->u_ixnetbase = OpenLibrary("ixnet.library", ix.ix_lib.lib_Version);
-
- me->tc_Launch = launch_glue;
- me->tc_Switch = switch_glue;
- me->tc_Flags |= TF_LAUNCH | TF_SWITCH;
- ix_u->u_itimerint.is_Node.ln_Type = NT_INTERRUPT;
- ix_u->u_itimerint.is_Node.ln_Name = me->tc_Node.ln_Name;
- ix_u->u_itimerint.is_Node.ln_Pri = 1;
- ix_u->u_itimerint.is_Data = (APTR) me;
- ix_u->u_itimerint.is_Code = (APTR) ix_timer;
-
-
- AddIntServer (INTB_VERTB, &ix_u->u_itimerint);
-
- ix_u->u_trace_flags = 1;
- ix_u->u_sync_mp = (struct MsgPort *) syscall (SYS_CreatePort, 0, 0);
- ix_u->u_select_mp = (struct MsgPort *) syscall (SYS_CreatePort, 0, 0);
-
- /* the CD storage. since 0 is a valid value for a lock, we use -1 */
- ix_u->u_startup_cd = (BPTR)-1;
-
- /* support for subprocesses a la Unix */
-
- /* each process starts out to be in its own process group. vfork()
- * scribbles over this to inherit the parents process group instead */
- ix_u->p_pgrp = (int) me;
- ix_u->p_pptr = (struct Process *) 1; /* hi init ;-)) */
- ix_u->p_cptr =
- ix_u->p_osptr =
- ix_u->p_ysptr = 0; /* no children to start with */
- ix_u->p_vfork_msg = 0;
- ix_u->p_zombie_sig = AllocSignal (-1);
- ix_u->u_rand_next = 1;
- NewList ((struct List *) &ix_u->p_zombies);
- strcpy(ix_u->u_logname, "unknown");
- ix_u->u_LogFile = -1;
- ix_u->u_LogTag = "syslog";
- ix_u->u_LogFacility = LOG_USER;
- ix_u->u_LogMask = 0xff;
- ix_u->u_a4_pointers_size = A4_POINTERS;
-
- if (ix_u->u_sync_mp && ix_u->u_select_mp)
- {
- ix_u->u_time_req = (struct timerequest *)
- syscall (SYS_CreateExtIO, ix_u->u_sync_mp, sizeof (struct timerequest));
-
- if (ix_u->u_time_req)
- {
- if (!OpenDevice (TIMERNAME, UNIT_MICROHZ,
- (struct IORequest *) ix_u->u_time_req, 0))
- {
- syscall (SYS_gettimeofday, &ix_u->u_start, 0);
-
- /* have to mask out ALL signals until ix_startup has had a
- * chance to setup its exit jmp_buf. If not, _longjmp will
- * generate a longjmp-botch using a not initialized jmpbuf! */
- syscall (SYS_sigsetmask, ~0);
-
- /* if enabled, set the red zone pointer for stack watch */
- if (ixbase->ix_red_zone_size)
- {
- struct Process *mep = (struct Process *) me;
- struct CommandLineInterface *CLI = BTOCPTR (mep->pr_CLI);
- u_int stack_size = CLI ? CLI->cli_DefaultStack * 4 : mep->pr_StackSize;
-
- /* I guess the above approach to find the correct stack
- size will work most of the time. But using tc_Lower
- as lower bound would probably not work. Thus I'm using
- the current stack value, not the unknown `real' top stack
- as top and subtract the stack_size to get to the bottom */
-
- if (stack_size > ixbase->ix_red_zone_size)
- ix_u->u_red_zone = (void *)(get_sp () - stack_size
- + ixbase->ix_red_zone_size);
- }
- if (__ix_open_muFS (ix_u))
- return ixbase;
- else
- {
- /* couldn't allocate muFS stuff */
- __ix_close_muFS (ix_u);
- }
- }
- /* couldn't open the timer device */
- syscall (SYS_DeleteExtIO, ix_u->u_time_req);
- }
- }
-
- if (ix_u->u_select_mp)
- syscall (SYS_DeletePort, ix_u->u_select_mp);
-
- if (ix_u->u_sync_mp)
- syscall (SYS_DeletePort, ix_u->u_sync_mp);
-
- RemIntServer (INTB_VERTB, &ix_u->u_itimerint);
- me->tc_Flags = ix_u->u_otask_flags;
- me->tc_Launch = ix_u->u_olaunch;
- FreeSignal (ix_u->u_sleep_sig);
- FreeSignal (ix_u->u_pipe_sig);
- FreeSignal (ix_u->p_zombie_sig);
-
- /* all_free() MUST come before we remove the pointer to u */
- all_free ();
- me->tc_TrapCode = ix_u->u_otrap_code;
- me->tc_TrapData = ix_u->u_otrap_data;
-
- kfree (tmp);
- }
-
- return 0;
- }
-